﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;

namespace Wheels.Windows
{
    public class HotKeyListener : MessageWindow
    {
#pragma warning disable 1591

        public event EventHandler<KeyPressedEventArgs> KeyPressed;
        private HashSet<int> mHoyKeys;
        private int mNextID;

        public HotKeyListener()
        {
            mHoyKeys = new HashSet<int>();
            Message += HotKeyListener_Message;
        }

        void HotKeyListener_Message(object sender, MessageWindow.MessageArgs e)
        {
            var m = e.SourceMessage;

            if (m.Msg == (int)User32.WM.HotKey)
            {
                Key key = (Key)(((int)m.LParam >> 16) & 0xFFFF);
                ModifierKeys modifier = (ModifierKeys)((int)m.LParam & 0xFFFF);

                if (KeyPressed != null)
                    KeyPressed(this, new KeyPressedEventArgs(m.WParam.ToInt32(), key, modifier));
            }
        }

        #region HotKeys

        public int RegisterHotKey(ModifierKeys modifier, Key key)
        {
            var currentID = mNextID;

            if (!User32.RegisterHotKey(Handle, currentID, modifier, key))
                throw new InvalidOperationException();

            mHoyKeys.Add(currentID);

            mNextID = mNextID + 1;
            return currentID;
        }

        public void UnregisterHotKey(int id)
        {
            User32.UnregisterHotKey(Handle, id);
            mHoyKeys.Remove(id);
        }

        private void UnregisterAllHotKeys()
        {
            foreach (var id in mHoyKeys.ToArray())
                UnregisterHotKey(id);

            mNextID = 0;
        }

        #endregion

        protected override void Dispose(bool disposing)
        {
            UnregisterAllHotKeys();

            base.Dispose(disposing);

            if (disposing)
            {
                mHoyKeys = null;
            }
        }
    }
}
